package com.bestcem.xm.common.core.sign.grpc.interceptor;

import com.bestcem.xm.common.core.exception.BusinessException;
import com.bestcem.xm.common.core.exception.UnauthorizedException;
import io.grpc.ForwardingServerCallListener;
import io.grpc.Metadata;
import io.grpc.ServerCall;
import io.grpc.ServerCall.Listener;
import io.grpc.Status;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class GrpcListener<ReqT, RespT> extends ForwardingServerCallListener.SimpleForwardingServerCallListener<ReqT> {

    private final ServerCall<ReqT, RespT> call;
    private final Metadata headers;

    public GrpcListener(Listener<ReqT> listener, ServerCall<ReqT, RespT> call, Metadata headers) {
        super(listener);
        this.call = call;
        this.headers = headers;
    }

    @Override
    public void onHalfClose() {
        try {
            super.onHalfClose();
        } catch (RuntimeException e) {
            handleException(e);
        }
    }

    @Override
    public void onReady() {
        try {
            super.onReady();
        } catch (RuntimeException e) {
            handleException(e);
        }
    }

    @Override
    public void onMessage(ReqT message) {
        super.onMessage(message);
    }

    private void handleException(RuntimeException e) {
        if (log.isErrorEnabled()) {
            log.error("[grpc] exception", e);
        }
        if (e instanceof UnauthorizedException) {
            call.close(Status.PERMISSION_DENIED.withDescription("unauthorized"), headers);
        } else if (e instanceof BusinessException) {
            BusinessException be = (BusinessException) e;
            call.close(Status.INVALID_ARGUMENT.withDescription(be.getDesc()), headers);
        } else {
            call.close(Status.UNKNOWN.withDescription(e.getMessage()), headers);
        }
    }

}
